library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library lib_expoRNS;


entity exponentiation_Calc is
	
	generic (
		Z : positive range 1 to 256 ;
		
		N : positive ;	-- Constantes nécessaire au calcul
		R : positive ;
		log2R : positive; 
		k : positive ;
		
		montgomery : boolean ;
		reel : boolean
	) ;
	port (
		clk : in std_logic ;
		a       : in std_logic_vector(Z-1 downto 0) ;  
		cmdMult : in std_logic_vector(1 downto 0) ;
		cmdX    : in std_logic ;
		cmdSave : in std_logic ;
		reset :   in std_logic ;
                start : in std_logic;
                is_ok : in std_logic;
		S       : out std_logic_vector(Z-1 downto 0)
	) ;
	
end entity;

-----------------------------------------------------------------------------------


architecture exponentiation_Calc1 of exponentiation_Calc is

--Importation de la montgomery multiplication unit
component Mult_Montg_Unit is
	generic(
		Z : positive range 1 to 256 := Z;
		N : positive := N ;
		R : positive := R;
                log2R : positive := log2R;
		k : positive := k	-- Constante nécessaire au calcul
	) ;
	port (
		a : in std_logic_vector(Z-1 downto 0) ;	
		b : in std_logic_vector(Z-1 downto 0) ;	
		is_active : in std_logic ;
		
		clk : in std_logic ;	-- Signal d'horloge
		reset : in std_logic ;
		c : out std_logic_vector(Z-1 downto 0) ;
		is_ready : out std_logic ;		
		is_end : out std_logic		
	) ;
end component ;


component Mult_Std_Unit
	generic(
		Z : positive range 1 to 256 := Z;	
		N : positive := N;	
		R : positive := R;
                log2R : positive := log2R;	
		k : positive := k 	
	) ;
	port (
		a : in std_logic_vector(Z-1 downto 0) ;
		b : in std_logic_vector(Z-1 downto 0) ;
		is_active : in std_logic ;	
		
		clk : in std_logic ;
		reset : in std_logic;
		c : out std_logic_vector(Z-1 downto 0) ;
		is_ready : out std_logic ;
		is_end : out std_logic	
	) ;

end component;
	
	
	signal X, E1,E2  : unsigned(Z-1 downto 0) ;
	signal X1, X2 : unsigned(Z-1 downto 0) := (others => '0');
	signal X_vect  : std_logic_vector(Z-1 downto 0) := (others => '0');
	signal is_ready,is_end : std_logic;
	
begin  -- exponentiation_Calc1

	S <= std_logic_vector(X1(Z-1 downto 0));
	
	-- Multiplication classique
	MultClassique: if montgomery = false generate
	with cmdMult select
		X <=	resize((X1)*(X1),Z) when "00",
			resize((X2)*(X2),Z) when "11",
			resize((X1)*(X2),Z) when others;
	end generate MultClassique;
	
	
	--Multiplication de montgomery
	multMontg: if montgomery = true generate
	
	X <= unsigned(X_vect);
	
	with cmdMult(0) select                -- Choix des entrées
		E1 <= X1 when '0',
			X2 when '1',
			(others => '0') when others;
	with cmdMult(1) select
		E2 <= X1 when '0',
			X2 when '1',
			(others => '0') when others;

  --Port Map

	reel_mult: if reel = true generate           -- Cas 2^n

	MMU_STD : Mult_Std_Unit
	port map (
		a => std_logic_vector(E1),
		b => std_logic_vector(E2),
		is_active => '1',
		clk => '0',
		reset => reset,
		c => X_vect,
		is_ready => is_ready,
		is_end => is_end
	);
	
	end generate reel_mult;
	
	Mong: if reel = false generate        -- Cas dans l'espace de montgomery
	
	
	MMU : Mult_Montg_Unit
	port map (
		a => std_logic_vector(E1),
		b => std_logic_vector(E2),
		is_active => '1',
		clk => clk,
		reset => reset,
		c => X_vect,
		is_ready => is_ready,
		is_end => is_end
	);
	end generate Mong;
	
	end generate multMontg;
	
	
	Memoire: process (cmdSave, reset, clk, start) --Mémoire
	begin  -- process
          if reset = '1' then
            X1 <= (others => '0');
            X2 <= (others => '0');
          end if;
          if clk'event and clk = '1' then  -- Sauvegarde
            if is_Ok = '1' then
              X1 <= unsigned(a);
              X2 <= (others => '0');
              
            elsif cmdSave = '1' then
              if cmdX = '0' then                -- On enregistre dans X1
                X1 <= X;
              else                              -- On enregistre dans X2
                X2 <= X;
              end if;
            end if;
          end if;
        end process;

        

end exponentiation_Calc1 ;

